Servlet Filter与HandlerInterceptor的对比
对于Servlet Filter,官方文档中说的很好, 并且给出了常见的应用场景。
A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, and a reference to the ServletContext which it can use, for example, to load resources needed for filtering tasks.
Filters are configured in the deployment descriptor of a web application.
Examples that have been identified for this design are:
- Authentication Filters
- Logging and Auditing Filters
- Image conversion Filters
- Data compression Filters
- Encryption Filters
- Tokenizing Filters
- Filters that trigger resource access events
- XSL/T filters
- Mime-type chain Filter
接下来用简单的例子进行理解。
示例
实现Filter接口。
1 | public class SimpleServletFilter implements Filter{ |
配置部署文件, filter所有的请求(?有问题,后面会说)。
1 | <filter> |
通过运行日志输出,结合前文HandlerInterceptor的对比,可以很清楚的看出filter和interceptor大概的生命周期。filter比interceptor更早出生,更晚死去。
1 | 2016-07-23 14:07:18,581 INFO SimpleServletFilter:16 - SimpleServletFilter init.... |
完整代码示例
知识点总结
- filter是比interceptor强大
- filter操纵request,response的能力更大,可以直接response回应客户端,但是在interceptor的preHandle方法中操纵response不起作用
- filter的粒度是更靠近前端的request级别,而interceptor处理的粒度测试靠近后端的Controller(或称为handler)的被映射的请求处理方法
- filter可以双向的,根据request或者response来响应,但是interceptor只能是拦截进入这一端
- 过程中发现,如果对静态资源配置了
<mvc:resources mapping="/resources/**" location="/resources/"/>
,那么如果访问的静态资源文件存在的话,filter并不会起作用(web.xml中的filter配置如下),即使把url-pattern指定为<url-pattern>/resources/*</url-pattern>
(其实/就匹配了所有的请求)。*说明了mvc:resources配置的静态文件并不会经过Servlet filter, 虽然说filter很强大。
1 | <filter> |
- 前面我说在interceptor的preHandle方法中操纵response不起作用,其实不够全面, 比如在preHandle方法中设置断点,当response回复消息后,此时shutdown服务器,这时在客户端会收到这里的消息。
- 另一种情况就更加奇怪,如果在interceptor中的 preHandle 方法中 response write消息之后是 return false,此时返回的消息同时包含了filter中被拦截成功后应该返回的消息(见下面),所以这时就崩溃了,一片混乱,所以只能在使用 handlerinterceptor 的时候不要使用response回复消息了。
1 | ➜ ~ curl http://localhost:8888/user/service\?id\=11 |
参考
(1)The Essentials of Filters
(2) interface HandlerInterceptor